import logging
import os
import sqlite3
from datetime import datetime
from typing import List, Union

from src.config import Config
from src.models import (
    FormerGraduateRecord,
    FreshGraduateRecord,
    PrintRecord,
)
from src.utils.mail_merge import (
    DeliveryTemplate,
    WJTZTemplate,
    YJTZTemplate,
    generate_kuaidi_xlsx,
    wj_mail_merge,
    yj_mail_merge,
)

IN_PRINT_LIST_IDS = set()
logger = logging.getLogger(__name__)


def camel_to_snake(name: str) -> str:
    """将驼峰式命名转换为下划线命名"""
    return "".join(["_" + c.lower() if c.isupper() else c for c in name]).lstrip("_")


def normalize_path(input_path, base_dir=None):
    """
    将不规范路径转换为当前系统的绝对路径
    :param input_path: 输入路径(相对/绝对，任意分隔符)
    :param base_dir: 基础目录(默认为当前工作目录)
    :return: 标准化后的绝对路径字符串
    """
    if base_dir is None:
        base_dir = os.getcwd()

    # 替换所有可能的分隔符为当前系统的分隔符
    normalized = input_path.replace("/", os.sep).replace("\\", os.sep)

    # 如果已经是绝对路径，直接标准化
    if os.path.isabs(normalized):
        return os.path.normpath(normalized)

    # 对于相对路径，结合基础目录处理
    return os.path.normpath(os.path.join(base_dir, normalized))


def generate_print_record(
    graduate_record: Union[FreshGraduateRecord, FormerGraduateRecord],
) -> PrintRecord:
    """根据FreshGraduateRecord生成PrintRecord"""
    if isinstance(graduate_record, FreshGraduateRecord):
        return PrintRecord.from_fresh_graduate_record(graduate_record)
    elif isinstance(graduate_record, FormerGraduateRecord):
        return PrintRecord.from_former_graduate_record(graduate_record)


def do_mail_merge_and_generate_kuaidi_xlsx(
    config: Config,
    print_records: List[PrintRecord],
    graduate_records: List[Union[FreshGraduateRecord, FormerGraduateRecord]],
) -> bool:
    """根据PrintRecord和GraduateRecord生成打印文件"""
    try:
        # 快递
        kuaidi_records_indices = [
            i
            for i, record in enumerate(print_records)
            if record.does_print_kuaidi == "是"
        ]
        kuaidi_graduate_records = [graduate_records[i] for i in kuaidi_records_indices]
        generate_kuaidi_xlsx(
            config.kuaidi_template_path,
            os.path.join(
                config.kuaidi_output_dir,
                f"{datetime.now().strftime('%Y%m%d%H%M%S')}.xlsx",
            ),
            [
                DeliveryTemplate.from_config_and_record(
                    config, record, item_details=f"{record.name}档案文件"
                )
                for record in kuaidi_graduate_records
            ],
        )
        # 本科应届
        benke_yjtz_records_indices = [
            i
            for i, record in enumerate(print_records)
            if record.does_print_tongzhi == "是"
            and record.print_type == "应届"
            and record.education_level == "本科"
        ]
        benke_yjtz_graduate_records = [
            graduate_records[i] for i in benke_yjtz_records_indices
        ]
        date_str = datetime.now().strftime("%Y-%m-%d")
        dir_path = os.path.join(config.yjtz_output_dir, date_str)
        os.makedirs(dir_path, exist_ok=True)
        for record in benke_yjtz_graduate_records:
            if isinstance(record, FreshGraduateRecord):
                yj_mail_merge(
                    config.yjtz_benke_template_path,
                    os.path.join(
                        dir_path,
                        f"{record.id}-{record.name}-应届{record.education_level}-{datetime.now().strftime('%Y%m%d%H%M%S')}.docx",
                    ),
                    YJTZTemplate.from_fresh_graduate_record(record),
                )
        # 研究生应届
        yanjiusheng_yjtz_records_indices = [
            i
            for i, record in enumerate(print_records)
            if record.does_print_tongzhi == "是"
            and record.print_type == "应届"
            and (record.education_level == "硕士" or record.education_level == "博士")
        ]
        yanjiusheng_yjtz_graduate_records = [
            graduate_records[i] for i in yanjiusheng_yjtz_records_indices
        ]
        date_str = datetime.now().strftime("%Y-%m-%d")
        dir_path = os.path.join(config.yjtz_output_dir, date_str)
        os.makedirs(dir_path, exist_ok=True)
        for record in yanjiusheng_yjtz_graduate_records:
            if isinstance(record, FreshGraduateRecord):
                yj_mail_merge(
                    config.yjtz_yanjiusheng_template_path,
                    os.path.join(
                        dir_path,
                        f"{record.id}-{record.name}-应届{record.education_level}-{datetime.now().strftime('%Y%m%d%H%M%S')}.docx",
                    ),
                    YJTZTemplate.from_fresh_graduate_record(record),
                )
        # 本科往届
        benke_wjtz_records_indices = [
            i
            for i, record in enumerate(print_records)
            if record.does_print_tongzhi == "是"
            and record.print_type == "非应届"
            and record.education_level == "本科"
        ]
        benke_wjtz_graduate_records = [
            graduate_records[i] for i in benke_wjtz_records_indices
        ]
        date_str = datetime.now().strftime("%Y-%m-%d")
        dir_path = os.path.join(config.yjtz_output_dir, date_str)
        os.makedirs(dir_path, exist_ok=True)
        for record in benke_wjtz_graduate_records:
            if isinstance(record, FormerGraduateRecord):
                wj_mail_merge(
                    config.wjtz_benke_template_path,
                    os.path.join(
                        dir_path,
                        f"{record.id}-{record.name}-非应届{record.education_level}-{datetime.now().strftime('%Y%m%d%H%M%S')}.docx",
                    ),
                    WJTZTemplate.from_former_graduate_record(record),
                )
        # 硕士往届
        shuoshi_wjtz_records_indices = [
            i
            for i, record in enumerate(print_records)
            if record.does_print_tongzhi == "是"
            and record.print_type == "非应届"
            and record.education_level == "硕士"
        ]
        shuoshi_wjtz_graduate_records = [
            graduate_records[i] for i in shuoshi_wjtz_records_indices
        ]
        date_str = datetime.now().strftime("%Y-%m-%d")
        dir_path = os.path.join(config.yjtz_output_dir, date_str)
        os.makedirs(dir_path, exist_ok=True)
        for record in shuoshi_wjtz_graduate_records:
            if isinstance(record, FormerGraduateRecord):
                wj_mail_merge(
                    config.wjtz_shuoshi_template_path,
                    os.path.join(
                        dir_path,
                        f"{record.id}-{record.name}-非应届{record.education_level}-{datetime.now().strftime('%Y%m%d%H%M%S')}.docx",
                    ),
                    WJTZTemplate.from_former_graduate_record(record),
                )
        # 博士往届
        boshi_wjtz_records_indices = [
            i
            for i, record in enumerate(print_records)
            if record.does_print_tongzhi == "是"
            and record.print_type == "非应届"
            and record.education_level == "博士"
        ]
        boshi_wjtz_graduate_records = [
            graduate_records[i] for i in boshi_wjtz_records_indices
        ]
        date_str = datetime.now().strftime("%Y-%m-%d")
        dir_path = os.path.join(config.yjtz_output_dir, date_str)
        os.makedirs(dir_path, exist_ok=True)
        for record in boshi_wjtz_graduate_records:
            if isinstance(record, FormerGraduateRecord):
                wj_mail_merge(
                    config.wjtz_boshi_template_path,
                    os.path.join(
                        dir_path,
                        f"{record.id}-{record.name}-非应届{record.education_level}-{datetime.now().strftime('%Y%m%d%H%M%S')}.docx",
                    ),
                    WJTZTemplate.from_former_graduate_record(record),
                )
    except Exception as e:
        logger.error(f"Error generating print files: {e}")
        return False
    return True


def _from_party_archive_lend_record_to_dict(v: str):
    v = v.strip()
    if v == "":
        return {"status": "", "records": []}
    status, *parts = [p.strip() for p in v.split(";") if p.strip()]
    records = []
    for seg in parts:
        dt_str, name, action = seg.split(" ")
        dt = datetime.strptime(dt_str, "%Y-%m-%d-%H:%M:%S")
        records.append({"dt": dt, "name": name, "action": action})
    return {"status": status, "records": records}


def _from_dict_to_party_archive_lend_record(v: dict):
    status = v["status"]
    records = v["records"]
    return f"{status}; " + "; ".join(
        f"{record['dt'].strftime('%Y-%m-%d-%H:%M:%S')} {record['name']} {record['action']}"
        for record in records
    )


def _check_graduate_records_ready(merged_results):
    succ_records = []
    fail_records = []
    fail_reasons = []
    for record in merged_results:
        if not record["degree_archive_status"]:
            # 学位档案未归档
            fail_records.append(record)
            fail_reasons.append("学位档案未归档")
            continue
        if not record["graduate_registration_form_status"]:
            # 毕业登记表未归档
            fail_records.append(record)
            fail_reasons.append("毕业登记表未归档")
            continue
        if not record["transcript_status"]:
            # 成绩单未归档
            fail_records.append(record)
            fail_reasons.append("成绩单未归档")
            continue
        if "党员" in record["political_status"]:
            party_archive_lend_record = _from_party_archive_lend_record_to_dict(
                record["party_archive_lend_record"]
            )
            if party_archive_lend_record["status"] != "已就绪":
                # 党员档案未归还
                fail_records.append(record)
                fail_reasons.append("党员档案未归还")
                continue
        succ_records.append(record)
    return succ_records, fail_records, fail_reasons


def check_graduate_records_ready(
    graduate_records: list[FormerGraduateRecord | FreshGraduateRecord],
    db_conn: sqlite3.Connection,
):
    benke_records = [
        record for record in graduate_records if record.education_level == "本科"
    ]
    shuoshi_records = [
        record for record in graduate_records if record.education_level == "硕士"
    ]
    boshi_records = [
        record for record in graduate_records if record.education_level == "博士"
    ]
    cursor = db_conn.cursor()
    merged_results = []
    if benke_records:
        parameters = []
        for record in benke_records:
            parameters.append(record.id)
            parameters.append(record.name)
        benke_query = """
                SELECT id, name, political_status, party_archive_lend_record, graduate_registration_form_status, 
                    degree_archive_status, transcript_status, graduation_status, archive_delivery_status 
                FROM benke_record 
                WHERE (id, name) IN ({})
                """.format(",".join(["(?, ?)"] * len(benke_records)))

        cursor.execute(benke_query, parameters)
        benke_results = cursor.fetchall()
        for row in benke_results:
            merged_results.append(
                {
                    "id": row[0],
                    "name": row[1],
                    "political_status": row[2],
                    "party_archive_lend_record": row[3],
                    "degree_archive_status": row[4] == "已归档",
                    "graduate_registration_form_status": row[5] == "已归档",
                    "transcript_status": row[6] == "已归档",
                    "graduation_status": row[7],
                    "archive_delivery_status": row[8],
                }
            )
    if shuoshi_records:
        parameters = []
        for record in shuoshi_records:
            parameters.append(record.id)
            parameters.append(record.name)
        yanjiusheng_query = """
                SELECT id, name, political_status, party_archive_lend_record, graduate_registration_form_status, 
                    degree_archive_status, graduation_status, archive_delivery_status 
                FROM shuoshi_record
                WHERE (id, name) IN ({})
                """.format(",".join(["(?, ?)"] * len(shuoshi_records)))
        cursor.execute(yanjiusheng_query, parameters)
        yanjiusheng_results = cursor.fetchall()
        for row in yanjiusheng_results:
            merged_results.append(
                {
                    "id": row[0],
                    "name": row[1],
                    "political_status": row[2],
                    "party_archive_lend_record": row[3],
                    "degree_archive_status": row[4] == "已归档",
                    "graduate_registration_form_status": row[5] == "已归档",
                    "graduation_status": row[6],
                    "archive_delivery_status": row[7],
                    "transcript_status": True,
                }
            )
    if boshi_records:
        parameters = []
        for record in boshi_records:
            parameters.append(record.id)
            parameters.append(record.name)
        boshi_query = """
                SELECT id, name, political_status, party_archive_lend_record, graduate_registration_form_status, 
                    degree_archive_status, graduation_status, archive_delivery_status 
                FROM boshi_record
                WHERE (id, name) IN ({})
                """.format(",".join(["(?, ?)"] * len(boshi_records)))
        cursor.execute(boshi_query, parameters)
        boshi_results = cursor.fetchall()
        for row in boshi_results:
            merged_results.append(
                {
                    "id": row[0],
                    "name": row[1],
                    "political_status": row[2],
                    "party_archive_lend_record": row[3],
                    "degree_archive_status": row[4] == "已归档",
                    "graduate_registration_form_status": row[5] == "已归档",
                    "graduation_status": row[6],
                    "archive_delivery_status": row[7],
                    "transcript_status": True,
                }
            )
    succ_records, fail_records, fail_reasons = _check_graduate_records_ready(
        merged_results
    )
    succ_records_ids = [record["id"] for record in succ_records]
    fail_records_ids = [record["id"] for record in fail_records]
    succ_records = [
        record for record in graduate_records if record.id in succ_records_ids
    ]
    fail_records = [
        record for record in graduate_records if record.id in fail_records_ids
    ]
    return succ_records, fail_records, fail_reasons


if __name__ == "__main__":
    import sqlite3

    from src.utils.load_config import load_config
    from src.utils.resources_path import resource_path

    config = load_config()
    db_path = resource_path(config.db_path)
    db_conn = sqlite3.connect(db_path)
    succ_records, fail_records, fail_reasons = check_graduate_records_ready(
        [
            FormerGraduateRecord(
                id="test",
                name="test",
                major="计算机科学与技术",
                send_time=datetime.now(),
                student_id_card_number="44010119900101001X",
                student_phone_number="13800000000",
                archives_recv_unit_name="中国大学Archives",
                archives_recv_address="中国 北京 北京市海淀区",
                archives_recvier="张三",
                archives_recvier_phone_number="13800000000",
                education_level="本科",
            ),
        ],
        db_conn,
    )
    print(succ_records)
    print(fail_records)
